package com.sanri.tools.modules.core.service.cc;

import com.sanri.tools.modules.core.exception.ToolException;
import com.sanri.tools.modules.core.service.cc.events.ConfigFileEvent;
import com.sanri.tools.modules.core.service.connect.dtos.ConnectTemplate;
import com.sanri.tools.modules.core.service.file.FileManager;
import com.sanri.tools.modules.core.service.plugin.events.ModuleChangeEvent;
import com.sanri.tools.modules.core.utils.OnlyPath;
import com.sanri.tools.modules.core.utils.WildcardMatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 通用配置维护,
 *
 * 这里模板不支持动态添加, 通过在 resources 中配置, 文件名模式为 cc.文件名.template.扩展名
 *
 * $configDir
 *   commonConfig
 *     $templateName.$extension
 *       file1: 具体的配置内容
 *       file2: 具体的配置内容
 */
@Service
@Slf4j
public class CommonConfigService implements InitializingBean, ApplicationListener<ModuleChangeEvent> {
    @Autowired
    private FileManager fileManager;

    /**
     * 通用配置目录
     */
    private static final String BASE_DIR = "commonConfig";

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 模板名列表
     * 这个返回的模板名指的是 模板名.后缀
     * @return
     */
    public String[] templateNames(){
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final String[] list = file.list();
        return list;
    }

    /**
     * 读取模板示例内容
     * @param templateName 模板名
     * @return
     */
    public String templateExample(String templateName) throws IOException {
        final String[] split = StringUtils.split(templateName, '.');

        final Resource[] resources = applicationContext.getResources("classpath*:cc."+split[0]+".template."+split[1]);
        if (resources == null || resources.length <= 0){
           throw new ToolException("未找到当前模板, 或模板已经被删除");
        }
        String content = IOUtils.toString(resources[0].getInputStream(), "utf-8");
        return content;
    }

    /**
     * 列出某个模板的文件列表
     * @param templateName 模板名 名称.后缀
     * @return
     */
    public String[] listTemplateFileNames(String templateName){
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final File templateDir = new File(file, templateName);
        if (templateDir.exists()){
            return templateDir.list();
        }
        return null;
    }

    /**
     * 列出某个模板的文件列表
     * @param templateName 模板名 名称.后缀
     * @return
     */
    public File[] listTemplateFiles(String templateName){
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final File templateDir = new File(file, templateName);
        if (templateDir.exists()){
            return templateDir.listFiles();
        }
        return null;
    }


    /**
     * 读取文件内容
     * @param templateName 模板名
     * @param baseName 基础名
     * @return
     */
    public String readTemplateFileContent(String templateName, String baseName) throws IOException {
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final File templateDir = new File(file, templateName);
        if (!templateDir.exists()){
            return null;

        }
        final File targetFile = new File(templateDir, baseName);
        if (!targetFile.exists()){
            return null;
        }

        final String content = FileUtils.readFileToString(targetFile, StandardCharsets.UTF_8);
        return content;
    }

    /**
     * 使用模板, 添加一个文件
     * @param templateName
     */
    public void editFile(String templateName, String baseName, String content) throws IOException {
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final File templateDir = new File(file, templateName);
        if (templateDir.exists()){
            final File targetFile = new File(templateDir, baseName);
            FileUtils.writeStringToFile(targetFile, content,StandardCharsets.UTF_8);
        }
    }

    /**
     * 删除一个通用配置
     * @param templateName
     * @param baseName
     */
    public void dropConfigFile(String templateName, String baseName){
        final File file = fileManager.mkConfigDir(BASE_DIR);
        final File templateDir = new File(file, templateName);
        if (templateDir.exists()){
            final File targetFile = new File(templateDir, baseName);
            targetFile.delete();
            applicationContext.publishEvent(new ConfigFileEvent(this));
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        final File commonConfigDir = fileManager.mkConfigDir(BASE_DIR);

        // 加载可用的模块, 每个模块自己注册配置模板, 只有注册了连接模板的模块才能创建配置 cc.[模板名].template.[文件格式]
        final Resource[] resources = applicationContext.getResources("classpath*:cc.*.template.*");
        for (Resource resource : resources) {
            final String filename = resource.getFilename();
            final String[] filenameSplit = StringUtils.splitPreserveAllTokens(filename, '.');

            // 在指定目录创建相关目录
            final File file = new File(commonConfigDir, filenameSplit[1] + "." + filenameSplit[3]);
            file.mkdirs();
        }
    }

    @Override
    public void onApplicationEvent(ModuleChangeEvent event) {
        final JarFile jarFile = (JarFile) event.getSource();
        if (event.isInstall()){
            // 动态安装插件
            final Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()){
                final JarEntry jarEntry = entries.nextElement();
                if (!jarEntry.isDirectory()){
                    final String name = jarEntry.getName();
                    final String filename = new OnlyPath(name).lastPath().toString();
                    final boolean match = WildcardMatch.match(filename, "cc.*.template.*");
                    if (match){
                        log.info("通用配置匹配, 新加通用配置模板: {}", filename);
                    }
                }
            }

        }else {

        }
    }
}
